Skip to content

hooks: defer internal OVS startup until charm has configured identity#168

Merged
gboutry merged 1 commit intocanonical:mainfrom
hemanthnakkina:fix-delay-ovs-start
Mar 25, 2026
Merged

hooks: defer internal OVS startup until charm has configured identity#168
gboutry merged 1 commit intocanonical:mainfrom
hemanthnakkina:fix-delay-ovs-start

Conversation

@hemanthnakkina
Copy link
Copy Markdown
Collaborator

When openstack-hypervisor and microovn are deployed simultaneously, snapd fires the configure hook immediately after snap install — before the charm has applied any snap config. At that point network.ovs-managed-by is still 'auto' and the ovn-chassis plug is not yet connected, so is_ovs_external() returns False. This caused _ensure_internal_ovs_services to start ovs-vswitchd, which creates the system@ovs-system kernel datapath. When microovn subsequently tries to initialise OVS it finds the datapath already in use and fails.

The same issue affects the second configure hook, triggered when the charm's own install hook calls snap set network.ovs-managed-by=auto, since the identity URL is still the placeholder at that point too.

Fix: before calling _ensure_internal_ovs_services, check whether identity.auth-url is still the placeholder default ("http://localhost:5000/v3"). While it is, the charm has not yet established its identity relation and internal OVS startup is deferred. Once the charm sets a real Keystone endpoint the guard clears and _ensure_internal_ovs_services runs normally.

The guard is only active when network.ovs-managed-by is 'auto'. When explicitly set to 'hypervisor' the operator's intent is unambiguous and ovs-vswitchd is started immediately regardless of identity.auth-url.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Defers starting internal OVS services during early configure hook runs until the charm has provided a non-placeholder Keystone endpoint, preventing openstack-hypervisor from pre-creating the system@ovs-system datapath and blocking a concurrently installing microovn.

Changes:

  • Add a guard in configure() to skip _ensure_internal_ovs_services() while network.ovs-managed-by=auto and identity.auth-url is still the default placeholder.
  • Update existing unit tests to account for the new guard.
  • Add new unit tests covering internal OVS startup deferral until identity is configured.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
openstack_hypervisor/hooks.py Adds identity-based guard to defer internal OVS service startup in auto mode.
tests/unit/test_hooks.py Adjusts existing configure-hook tests and adds new tests for the startup guard.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread openstack_hypervisor/hooks.py Outdated
Comment thread tests/unit/test_hooks.py
When openstack-hypervisor and microovn are deployed simultaneously,
snapd fires the configure hook immediately after snap install — before
the charm has applied any snap config.  At that point
network.ovs-managed-by is still 'auto' and the ovn-chassis plug is not
yet connected, so is_ovs_external() returns False.  This caused
_ensure_internal_ovs_services to start ovs-vswitchd, which creates the
system@ovs-system kernel datapath.  When microovn subsequently tries to
initialise OVS it finds the datapath already in use and fails.

The same issue affects the second configure hook, triggered when the
charm's own install hook calls `snap set network.ovs-managed-by=auto`,
since the identity URL is still the placeholder at that point too.

Fix: before calling _ensure_internal_ovs_services, check whether the
charm has applied its identity configuration.  The guard defers OVS
startup when BOTH identity.auth-url is still the placeholder default
("http://localhost:5000/v3") AND identity.username is unset (None).
Checking both fields ensures the guard still clears correctly for
operators that legitimately run Keystone at http://localhost:5000/v3,
since those deployments will always set identity.username.  Once either
condition is no longer true the guard clears and _ensure_internal_ovs_services
runs normally.

The guard is only active when network.ovs-managed-by is 'auto'.  When
explicitly set to 'hypervisor' the operator's intent is unambiguous and
ovs-vswitchd is started immediately regardless of identity state.
@hemanthnakkina hemanthnakkina marked this pull request as ready for review March 25, 2026 02:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/unit/test_hooks.py
Comment on lines +1761 to +1764
snap.config.get_options.return_value.get.return_value = hooks.DEFAULT_CONFIG[
"identity.auth-url"
]

Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this test, snap.config.get_options.return_value.get.return_value is set to the default auth URL, which means the mocked identity_opts.get() will also return that same string for identity.username. That makes the startup guard evaluate as “configured” even if _OVS_MANAGED_BY were still auto, so the test can pass without actually exercising the intended bypass behavior for OVS_MANAGED_BY_HYPERVISOR. Mock identity_opts.get() with a side_effect that returns the placeholder URL for identity.auth-url and None for identity.username so the guard would defer in auto but is bypassed in hypervisor.

Suggested change
snap.config.get_options.return_value.get.return_value = hooks.DEFAULT_CONFIG[
"identity.auth-url"
]
identity_opts = snap.config.get_options.return_value
def _identity_get_side_effect(option, default=None):
if option == "identity.auth-url":
# Still at the placeholder default.
return hooks.DEFAULT_CONFIG["identity.auth-url"]
if option == "identity.username":
# Username has not been configured yet.
return None
return default
identity_opts.get.side_effect = _identity_get_side_effect

Copilot uses AI. Check for mistakes.
Comment thread tests/unit/test_hooks.py
Comment on lines +1676 to +1677
placeholder default. In that state ``_ensure_internal_ovs_services`` must be
skipped to avoid creating ``system@ovs-system`` before microovn installs.
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This docstring says the snap defers startup by checking only that identity.auth-url equals the placeholder default, but the actual guard in configure() also requires identity.username to be unset. Please update the docstring to reflect the real condition (auth-url placeholder AND username unset) so the test description matches the behavior under test.

Suggested change
placeholder default. In that state ``_ensure_internal_ovs_services`` must be
skipped to avoid creating ``system@ovs-system`` before microovn installs.
placeholder default *and* that ``identity.username`` is still unset. In that
state ``_ensure_internal_ovs_services`` must be skipped to avoid creating
``system@ovs-system`` before microovn installs.

Copilot uses AI. Check for mistakes.
@gboutry gboutry merged commit da59891 into canonical:main Mar 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants